package d20chat;

import java.util.regex.*;
import java.util.Scanner;
import javax.swing.JOptionPane;


/********************************************************************************
Handles messages coming to the client.
********************************************************************************/
public class IncomingMessageParser 
{
    /** the ui component for displaying text. */
    private d20chatui tempui;
    /**
     * where we can find information about the user.
     */
    private D20Chat theMain;
    /**
     * a copy of the message sent from the server.
     */
    private String receivedMessage;
    /** the name of the last person to send a /tell */
    public String lastPerson = "";
    /**
     * the name of the person who sent the current message.
     */
    private String originName; 
    /**
     * gives a basic idea of how the message will be handled.
     * can be chat, command, or request.
     */
    private String type; 
    /**
     * exact type of message.
     */
    private String subType; 
    /**
     * who the message is about.
     */
    private String targetName; 
    /**
     * used for on/off type commands.
     */
    private String state; 
    /**
     * the index of the actual chat message in the receivedMessage.
     */
    private int posMessageStart; 
    
    
    /**
     * Checks the type of message and sends it to the appropriate methods to handle it.
     * @param message a formatted message sent to the client
     */
    public void CheckType(String message)
    {
        //stores the message
        receivedMessage = message;

        
        //stores a compiled regular expression that pulls out words
        Pattern wordPattern = Pattern.compile( ".*?\\s" );
        //object to connect our word expression to our message
        Matcher matcher = wordPattern.matcher( receivedMessage );
        
        //find the first word in the message
        if( matcher.find() )
        {
            //this word will be the name of the person with whom the message originated
            originName = receivedMessage.substring(matcher.start(), matcher.end()-1);
        }
        
        //find the next word in the message
        if( matcher.find() )
        {
            //this word will be either chat or command
            type = receivedMessage.substring(matcher.start(), matcher.end()-1);
        }
        
        //find the next word
        if( matcher.find() )
        {
            //this word will be the subtype such as tell or say for chat or silence for command
            subType = receivedMessage.substring(matcher.start(), matcher.end()-1);
        }
        
        //find the next word
        if( matcher.find() )
        {
            //this word will be the name of the person the message is about
            targetName = receivedMessage.substring(matcher.start(), matcher.end()-1);
            
            //after this word a chat message would begin, store this point
            posMessageStart = matcher.end();
        }
        
        if( matcher.find() )
        {
            //this word will be a state message for some commands such as on or off for silence
            state = receivedMessage.substring(matcher.start(), matcher.end()-1);
        }
        
        //check to see if the type is chat, command, or request and call the corresponding function
        if( type.equals( "chat" ) )
        {
            //call the function chat() to format the final message that will display on the screen
            chat();
        }
        else if( type.equals( "command" ) )
        {
            //call the function command to handle any client side chores and format final message
            command(); 
        }
        else if( type.equals( "request" ) )
        {
            //call the function request to handle any client side chores and format final message
            request();
        }

    }
    
    
    /**
     * Handles messages that just needs to be formatted and displayed in the chat window.
     */
    private void chat()
    {
        String finalMessage = ""; //the string to hold the formatted message

        if( theMain.theSettings.overwrite == true )
        {
            //if the user wants only font formatting originating from them
            //remove the html from the message
            stripHTML();
        }
        
        if( subType.equals("systemMessage"))
        {
            //add that it's a system message it and display it.
            finalMessage = "System Message : " + receivedMessage.substring( posMessageStart ) + "\n";
        }
        else if( subType.equals("say"))
        {
            if( originName.equals(theMain.theUser.getUsername()) )
            {
                //the say comes from this user so output it as coming from them
                finalMessage = "You say " + receivedMessage.substring( posMessageStart ) + "\n";
            }
            else
            {
                //the say comes from another user, say who
                finalMessage = originName + " says " + receivedMessage.substring( posMessageStart ) + "\n";
            }

        }
        else if( subType.equals("emote"))
        {
                //say who is doing the emote
                //even if it's the user it makes more grammatical sense to use their name than you
                finalMessage = originName + " " + receivedMessage.substring( posMessageStart ) + "\n";
        }
        else if( subType.equals("tell"))
        {
            if( originName.equals(theMain.theUser.getUsername()) )
            {
                //the tell comes from this user, so output it as coming from them
                finalMessage = "You tell " + targetName + " " + receivedMessage.substring( posMessageStart ) + "\n";
            }
            else
            {
                lastPerson = originName;
                //the tell comes from another user, say who
                finalMessage = originName + " tells you " + receivedMessage.substring( posMessageStart ) + "\n";
            }
        }
        else if( subType.equals("hide"))
        {
            if( originName.equals(theMain.theUser.getUsername()) )
            {
                //a message from this user that is only seen by them, indicate that
                //by adding hidden to the message
                finalMessage = "Hidden : " + receivedMessage.substring( posMessageStart ) + "\n";
            }
        }

        //now that the message has been formatted display it in the chat window
        tempui.tempchatwindowoutput( finalMessage );
     }
    
    
    /**
     * Handles messages from or about players.
     * Responds to messages that require it.
     * Alters variables on client end if necessary.
     */
    private void request()
    {
        String info;
        String finalMessage;
        
        if( subType.equals( "requestUserInfo" ) )
        {   
            info = "/userInfo " + theMain.theUser.toString();   
            theMain.OutParse.sendMessage( info );
        }
        else if( subType.equals( "playersList" ) )
        {
            info = receivedMessage.substring( posMessageStart );

            String[] names = info.split("\u8594");
            tempui.playernames = names;
             
            tempui.refreshplayer();
        }
        else if( subType.equals( "password" ) )
        {
            if( theMain.serverPassword.isEmpty() )
            {
                //pop up box asking for password and send would be better
                info = "/password empty";
                theMain.OutParse.sendMessage( info );
            }
            else
            {   
                //send password
                info = "/password " + theMain.serverPassword.toString();   
                theMain.OutParse.sendMessage( info );
            }
        }
        else if(subType.equals( "profile" ) )
        {
            info = "junk " + receivedMessage.substring( posMessageStart );
            
            //Pop up ShowProfile form
            ShowProfile sp;
            sp = new ShowProfile(info);
            sp.setVisible(true);
        }
        else if(subType.equals( "charsheet" ) )
        {
            info = "/sendcharsheet " + originName + " " + tempui.getcharsheet();
            theMain.OutParse.sendMessage( info );
        }
        else if(subType.equals( "sendcharsheet" ) )
        {
            info = receivedMessage.substring( posMessageStart );
            ShowCharacter cs;
            System.out.println( info );
            cs = new ShowCharacter(info, originName);
            cs.setVisible(true);
        }
        else if(subType.equals( "charNameChange" ) )
        {
            Scanner pieceScanner = new Scanner( receivedMessage );
            pieceScanner.useDelimiter( "\u8594" );

            if( pieceScanner.hasNext() )
            {
                //junk piece
             pieceScanner.next();

            }
            if( pieceScanner.hasNext() )
            {
                String newName = pieceScanner.next();
                tempui.changeplayer(originName, originName, newName);
            }
        }        
        else if( subType.equals( "changeName" ))
        {
            finalMessage = originName + " has changed their name to " + targetName + "\n";
            tempui.changeplayer(originName, targetName, receivedMessage.substring( posMessageStart ));
            tempui.tempchatwindowoutput( finalMessage );
        }
    }
    
    
    /**
     * Handles messages from gm or that effect everyone in the room.
     */
    private void command()
    {
        //this is messages about silence, kick, add, remove, charactersheets ect.
        
        String finalMessage = "";
        String action;
        
        if( subType.equals("silence"))
        {
            silence();
        }
        else if( subType.equals( "kick" ))
        {
            finalMessage = "The GM has kicked " + targetName +".\n";
            tempui.tempchatwindowoutput( finalMessage );
            
            // If the current client is the kickee then let the user know
            if (theMain.theUser.getUsername().equals(targetName))
                JOptionPane.showMessageDialog(null, "You have been kicked from the room.", "D20 Chat", JOptionPane.ERROR_MESSAGE);
        }
        else if( subType.equals( "charactersheet" ))
        {
            if( state.equals( "on" ) )
            {
                finalMessage = "You may now view other player's charactersheets.\n";
            }
            else if( state.equals( "off" ) )
            {
                finalMessage = "Other player's character sheets are now hidden.\n";
            }
            tempui.tempchatwindowoutput( finalMessage );
            
        }
        else if( subType.equals( "leaveRoom" ))
        {
            finalMessage = originName + " has left the room.\n";
            tempui.tempchatwindowoutput( finalMessage );
            tempui.removeplayer(originName);
            
            // If the current client leaves the room then let the user know
            if (theMain.theUser.getUsername().equals(originName))
                JOptionPane.showMessageDialog(null, "You have left the room.", "D20 Chat", JOptionPane.INFORMATION_MESSAGE);
        }
        else if( subType.equals( "joinRoom" ))
        {
            finalMessage = originName + " has joined the room.\n";
            tempui.tempchatwindowoutput( finalMessage );
            tempui.addplayer(originName, receivedMessage.substring( posMessageStart ) );
        }
        else if( subType.equals( "changeName" ))
        {
            finalMessage = originName + " has changed their name to " + targetName + "\n";
            tempui.tempchatwindowoutput( finalMessage );
            tempui.changeplayer(originName, targetName, receivedMessage.substring( posMessageStart ));
        }
        else if( subType.equals("makeGM"))
        {
            finalMessage = targetName + " is now the GM.\n";
            tempui.tempchatwindowoutput( finalMessage );
        }
        else
        {
            //echo message for testing
            tempui.tempchatwindowoutput( receivedMessage );
        }

    }
    
    
    /**
     * Strips any text between < and > out of the message to remove html.
     */
     private void stripHTML()
    {
        //find text braketed by < and > in the unparsed message
        receivedMessage = receivedMessage.replaceAll("\\<.*?\\>","");
    }
     
     

    /**
     * Displays a message about silence action.
     */
    private void silence()
    {
        String action = "";

        if( state.equals("on") )
        {
            if( targetName.equalsIgnoreCase( theMain.theUser.getUsername() ) )
            {
                action = "The GM has silenced you.\n";
            }
            else if( targetName.equalsIgnoreCase( "all" ) )
            {
                action = "The GM has silenced all players.\n";
            }
            else
            {
                action = "The GM has silenced " + targetName + ".\n";
            }
        }
        else if( state.equals("off") )
        {
             if( targetName.equalsIgnoreCase( theMain.theUser.getUsername() ) )
            {
                action = "The GM has given you permission to speak.\n";
            }
            else if( targetName.equalsIgnoreCase( "all" ) )
            {
                action = "The GM has given all players permission to speak.\n";
            }
            else
            {
                action = "The GM has given " + targetName + " permission to speak.\n";
            }
        }

        tempui.tempchatwindowoutput ( action );
    }   
    
    
    /**
     * Creates a new instance of IncomingMessageParser
     * @param gui The user interface for the program.
     * @param thisD20Chat The main class for the program.
     */
    public IncomingMessageParser( d20chatui gui, D20Chat thisD20Chat ) 
    {
        tempui = gui;
        theMain = thisD20Chat;
    }
}
